home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / actlib11.zip / CALC.ZIP / CALC.C next >
C/C++ Source or Header  |  1993-02-25  |  4KB  |  174 lines

  1. /*
  2.  *  Copyright (C) 1993   Marc Stern  (internet: stern@mble.philips.be) 
  3.  *
  4.  *  CALC
  5.  *
  6.  *  Topic :             Mathematical expression evaluation
  7.  *
  8.  *  Allowed operators : + - * / () = < > <= >= <>   on floating point numbers
  9.  *                                              %   on integer numbers
  10.  *
  11.  */
  12.  
  13.  
  14.  
  15.  
  16. #include "calc.h"
  17. #include <math.h>
  18. #include <ctype.h>
  19. #include <stdio.h>
  20.  
  21.  
  22.  
  23. static long double near get_expr( ) ;
  24. static long double near fetch_operand( ) ;
  25.  
  26.  
  27.  
  28. static char *string ;
  29.  
  30.  
  31.  
  32.  
  33.  
  34. /*******************************************************
  35.  *
  36.  * Function     : get_expr
  37.  * Topic        : evaluate a mathematical expression
  38.  * Return       : value of the expression or HUGE_VAL
  39.  * Input        : string pointer (static variable)
  40.  * Side-effects : string will begin after expression
  41.  *
  42.  *******************************************************
  43.  */
  44.  
  45. long double near get_expr( )
  46.  
  47. {
  48.   long double operand1 , operand2 , result = 0 ;
  49.   char  operator1 = '+' , operator2 ;
  50.  
  51.   for ( ; *string ; string++ )
  52.       {
  53.     operand1 = fetch_operand() ;
  54.     if ( operand1 == HUGE_VAL ) return(HUGE_VAL) ;
  55.  
  56.     operator2 = *string ;
  57.     while ( (*string == '*') || (*string == '/') || (*string == '%') || (*string == '<') || (*string == '>') || (*string == '=') )
  58.           {
  59.         string++ ;
  60.  
  61.         if ( *string == '=' )
  62.                    switch( operator2 )
  63.                  {
  64.                case '>' : operator2 = '≥' ; string++ ; break ;
  65.                case '<' : operator2 = '≤' ; string++ ; break ;
  66.                case '=' : operator2 = '=' ; string++ ; break ;
  67.                  }
  68.  
  69.         if ( (operator2 == '<') && (*string == '>') )
  70.                    {
  71.                      operator2 = '≡' ;
  72.                      string++ ;
  73.                    }
  74.  
  75.         operand2 = fetch_operand() ;
  76.         if ( operand2 == HUGE_VAL ) return(HUGE_VAL) ;
  77.  
  78.         switch( operator2 )
  79.               {
  80.             case '*' : operand1 *= operand2 ; break ;
  81.             case '/' : operand1 /= operand2 ; break ;
  82.             case '%' : operand1 = (long double) ( (int) operand1 % (int) operand2 ) ; break ;
  83.             case '=' : operand1 = (operand1 == operand2) ; break ;
  84.             case '>' : operand1 = (operand1 > operand2) ; break ;
  85.             case '≥' : operand1 = (operand1 >= operand2) ; break ;
  86.             case '<' : operand1 = (operand1 < operand2) ; break ;
  87.             case '≤' : operand1 = (operand1 <= operand2) ; break ;
  88.             case '≡' : operand1 = (operand1 != operand2) ; break ;
  89.               }
  90.         operator2 = *string ;
  91.           }
  92.     if ( operator1 == '+' ) result += operand1 ;
  93.                else result -= operand1 ;
  94.     if ( (! *string) || (operator2 == ')') ) break ;
  95.     operator1 = operator2 ;
  96.       }
  97.  
  98.   return( result ) ;
  99. }
  100.  
  101.  
  102. /*******************************************************
  103.  *
  104.  * Function     : fetch_operand
  105.  * Topic        : fetch one operand or (...)
  106.  * Return       : value of the operand or (...)
  107.  * Input        : string pointer (static variable)
  108.  * Side-effects : string will begin after expression
  109.  *
  110.  *******************************************************
  111.  */
  112.  
  113. long double near fetch_operand()
  114.  
  115. {
  116.   long double result ;
  117.   char op_str[255] , *operand ;
  118.  
  119.   if ( *string == '(' ) { string++ ;
  120.                result = get_expr() ;
  121.                if ( (result == HUGE_VAL) || (*string != ')') )
  122.                   return(HUGE_VAL) ;   /*  ) missing  */
  123.                string++ ;
  124.              }
  125.            else { operand = op_str ;
  126.                           if ( *string == '-' ) *operand++ = *string++ ;
  127.               while ( *string && (isdigit(*string) || (*string == '.')) )
  128.                 *operand++ = *string++ ;
  129.               *operand = '\0' ;
  130.               if ( sscanf(op_str , "%Lf" , &result) != 1 )
  131.                  return(HUGE_VAL) ;  /*  empty value or too large  */
  132.             }
  133.  
  134.   switch( *string ) { case '\0':
  135.               case ')' :
  136.               case '+' :
  137.               case '-' :
  138.               case '*' :
  139.               case '/' :
  140.               case '%' :
  141.               case '<' :
  142.               case '>' :
  143.               case '=' :
  144.                  break ;
  145.  
  146.               default  : return(HUGE_VAL) ;   /*  Bad operator  */
  147.             }
  148.  
  149.   return(result) ;
  150. }
  151.  
  152.  
  153. long double calc( char *calcul )
  154.  
  155. { long double result ;
  156.   char *ptr1 , *ptr2 ;
  157.  
  158.   for ( ptr1 = ptr2 = calcul ; *ptr1 ; *ptr1++ = *ptr2++ )
  159.       while ( *ptr2== ' ' || *ptr2== '\t' ) ptr2++ ;
  160.  
  161.   *ptr2 = '\0' ;
  162.  
  163.   string = calcul ;
  164.  
  165.   result = get_expr() ;
  166.  
  167.   if ( result == HUGE_VAL ) *calcul = '\0' ;
  168.                        else { /*  suppress trailing '0' (and final '.')  */
  169.                   sprintf( calcul , "%Lf" , result ) ;
  170.                   simplify( calcul ) ;
  171.                 }
  172.   return(result) ;
  173. }
  174.